home *** CD-ROM | disk | FTP | other *** search
- /*
- * instruction.c
- * Manage instructions.
- *
- * Copyright (c) 1996 Systems Architecture Research Centre,
- * City University, London, UK.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * Written by Tim Wilkinson <tim@sarc.city.ac.uk>, February 1996.
- */
-
- #define IDBG(s)
-
- #include <assert.h>
- #include <stdio.h>
- #include "instruction.h"
- #include "register.h"
- #include "constants.h"
- #include "classMethod.h"
- #include "gen.h"
- #include "exception.h"
- #include "translator.h"
- #include "soft.h"
-
- #define MAXLNK 512
- #define NCODESIZE 16*1024
- #define NCODERED 64
-
- struct {
- bool internal;
- int pos;
- int pc;
- int relpc;
- } lnkTable[MAXLNK];
-
- int jtpos;
- nativecode ncodebuf[NCODESIZE+NCODERED];
- nativecode* pc;
-
- void
- dumpInstn(methods* m)
- {
- int i;
- int nrop;
- instn* ipc;
- int nr;
-
- IDBG( printf("Method `%s:%s' : flgs=0x%x in=%d, out=%d, local=%d, stk=%d\n",
- m->class->name, m->name, m->accflags, m->ins,
- m->outs, m->localsz, m->stacksz); )
-
- pc = ncodebuf;
- m->ncode = 0;
- ipc = m->insn;
- nr = m->codelen;
- jtpos = 0;
-
- INSTRUCTION_PROLOGUE(m->localsz);
-
- /* If this is a synchronised method, make sure we enter the monitor
- now. */
- if (m->accflags & ACC_SYNCHRONISED) {
- INSTRUCTION_MONITORENTER(m);
- }
-
- for (; nr > 0; nr--, ipc++) {
- ipc->addr = (int)pc;
- nrop = instnTable[ipc->op].in;
- for (i = 0; i < nrop; i++) {
- if (ipc->in[i].valid == true) {
- INSTRUCTION_POP(ipc->in[i].reg);
- }
- }
- (*(genfunc)instnTable[ipc->op].func)(ipc);
- nrop = instnTable[ipc->op].out;
- for (i = nrop - 1; i >= 0; i--) {
- if (ipc->out[i].valid == true) {
- INSTRUCTION_PUSH(ipc->out[i].reg);
- }
- }
-
- /* Cannot overrun the ncode buffer */
- if (pc > &ncodebuf[NCODESIZE]) {
- fprintf(stderr, "Internal error: too little ncode space.\n");
- abort();
- }
- }
-
- /* Move the code to a malloced buffer then fill in the jumps */
- m->ncode = (nativecode*)malloc(pc - ncodebuf);
- if (m->ncode == 0) {
- abort();
- }
- m->ncode_end = m->ncode + (pc - ncodebuf);
- memcpy(m->ncode, ncodebuf, pc - ncodebuf);
- fillinLinks(m);
- }
-
- /*
- * Add a relative link to the link table for later fixup.
- */
- void
- addLink(int offset, int point, int relpoint, bool in)
- {
- lnkTable[jtpos].internal = in;
- lnkTable[jtpos].pos = offset;
- lnkTable[jtpos].pc = point;
- lnkTable[jtpos].relpc = relpoint;
- jtpos++;
- if (jtpos == MAXLNK) {
- fprintf(stderr, "Internal error: Out of jump table space.\n");
- exit(1);
- }
- }
-
- /*
- * Run down link table fixing up links.
- */
- fillinLinks(methods* m)
- {
- int i;
- instn* ipc;
- int clen;
- int adjust;
-
- ipc = m->insn;
- clen = m->codelen;
- adjust = m->ncode - ncodebuf;
-
- for (i = 0; i < jtpos; i++) {
- if (lnkTable[i].internal == true) {
- assert(lnkTable[i].pos >= 0);
- assert(lnkTable[i].pos < clen);
- *(int*)(lnkTable[i].pc + adjust) = ipc[lnkTable[i].pos].addr - lnkTable[i].relpc;
- }
- else {
- *(int*)(lnkTable[i].pc + adjust) = lnkTable[i].pos - (lnkTable[i].relpc + adjust);
- }
- }
- }
-
- /*
- * Translate exception table.
- */
- void
- dumpExceptions(methods* m)
- {
- int i;
- exception* e;
- int adjust;
-
- /* If no exception table then ignore */
- if (m->exception_table == 0) {
- return;
- }
-
- adjust = m->ncode - ncodebuf;
-
- /* Translate into real addresses */
- for (i = 0; i < m->exception_table_len; i++) {
- e = &m->exception_table[i];
- e->start_pc = m->insn[e->start_pc].addr + adjust;
- e->end_pc = m->insn[e->end_pc].addr + adjust;
- e->handler_pc = m->insn[e->handler_pc].addr + adjust;
- }
- }
-
- /*
- * Translate lookup and table switches.
- */
- void
- dumpSwitches(methods* m)
- {
- tableswitch* table;
- lookupswitch* lookup;
- int adjust;
- int i;
-
- adjust = m->ncode - ncodebuf;
-
- for (table = m->tableswitches; table != 0; table = table->next) {
- for (i = 0; i < table->len; i++) {
- table->offsets[i] = m->insn[table->offsets[i]].addr + adjust;
- }
- }
-
- for (lookup = m->lookupswitches; lookup != 0; lookup = lookup->next) {
- for (i = 0; i < lookup->len; i++) {
- lookup->offsets[i*2+1] = m->insn[lookup->offsets[i*2+1]].addr + adjust;
- }
- }
- }
-